package com.zlyx.easy.core.map;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import com.zlyx.easy.core.loggers.Logger;

/**
 * <p>
 * Map操作工具类
 * </p>
 *
 * @author 赵光
 * @since 2020年1月10日
 */
public final class Maps {

	/**
	 * EasyMap
	 * 
	 * @return
	 */
	public static <K, V> EasyMap<K, V> newMap() {
		return new EasyMap<K, V>();
	}

	/**
	 * EasyMap
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public static <K, V> EasyMap<K, V> newMap(K key, V value) {
		return new EasyMap<K, V>().addValue(key, value);
	}

	/**
	 * EasyMap
	 * 
	 * @param map
	 * @return
	 */
	public static <K, V> EasyMap<K, V> newMap(Map<K, V> map) {
		return new EasyMap<K, V>().addValue(map);
	}

	/**
	 * 根据Object对象数组解析创建hashMap
	 * 
	 * @param <T>
	 * @param key
	 * @param value
	 * @return
	 */
	public static EasyMap<String, String> newMap(Object... os) {
		Objects.requireNonNull(os);
		EasyMap<String, String> map = newMap();
		if (os.length % 2 != 0) {
			Logger.warn("Wrong length of os:" + os.length);
			return map;
		}
		for (int i = 0; i < os.length; i++) {
			map.put(String.valueOf(os[i]), String.valueOf(os[i + 1]));
			i++;
		}
		return map;
	}

	/**
	 * 解析字符串为map
	 * 
	 * @param kvs 格式为"key1:1;key2:2;key3:3"
	 * @return
	 */
	public static EasyMap<String, String> newMap(String text) {
		Objects.requireNonNull(text);
		String[] arr = null;
		EasyMap<String, String> map = newMap();
		for (String kv : text.split(";")) {
			if (kv.contains(":")) {
				arr = kv.split(":");
				if (arr.length > 1) {
					map.put(arr[0].trim(), arr[1].trim());
				}
			}
		}
		return map;
	}

	/**
	 * 转换map
	 * 
	 * @param map
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> EasyMap<String, T> wrapMap(Map<String, Object> map) {
		EasyMap<String, T> tmp = newMap();
		for (String key : map.keySet()) {
			tmp.put(key, (T) map.get(key));
		}
		return tmp;
	}

	/**
	 * 反转map
	 * 
	 * @param map
	 * @return
	 */
	public static <K, V> EasyMap<V, K> revertMap(Map<K, V> map) {
		return newMap(map).revertMap();
	}

	/**
	 * toMultiMap
	 * 
	 * @param map
	 * @return
	 * @throws Exception
	 */
	public static <K, V> MultiValueMap<K, V> toMultiMap(Map<K, V> map) {
		MultiValueMap<K, V> dataMap = new LinkedMultiValueMap<>();
		dataMap.setAll(map);
		return dataMap;
	}

	/**
	 * toSingleMap
	 * 
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public static <K, V> Map<K, V> toSingleMap(Map<K, List<V>> dataMap) {
		Map<K, V> map = new HashMap<>();
		dataMap.forEach((key, values) -> {
			if (values != null) {
				map.put(key, values.get(0));
			}
		});
		return map;
	}

	/**
	 * 根据value取key
	 * 
	 * @param <K>
	 * @param <V>
	 * @param map
	 * @param value
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <K, V> K getKey(Map<K, V> map, V value) {
		if (map != null && map.containsValue(value)) {
			Object[] values = map.values().toArray();
			for (int i = 0; i < values.length; i++) {
				if (values[i].equals(value)) {
					return (K) map.keySet().toArray()[i];
				}
			}
		}
		return null;
	}

	/**
	 * 判断参数Map是否为空
	 * 
	 * @param map
	 * @return
	 */
	public static boolean isEmpty(Map<?, ?> map) {
		return map == null || map.size() == 0;
	}

	/**
	 * 判断参数map是否不为空
	 * 
	 * @param map
	 * @return
	 */
	public static boolean isNotEmpty(Map<?, ?> map) {
		return !isEmpty(map);
	}

	/**
	 * newHashMap
	 * 
	 * @return
	 */
	public static <K, V> Map<K, V> newHashMap() {
		return new HashMap<K, V>();
	}

	/**
	 * newConcurrentHashMap
	 * 
	 * @return
	 */
	public static <K, V> Map<K, V> newConcurrentHashMap() {
		return new ConcurrentHashMap<>();
	}

	/**
	 * newLinkedHashMap
	 * 
	 * @return
	 */
	public static <K, V> Map<K, V> newLinkedHashMap() {
		return new LinkedHashMap<K, V>();
	}

	/****
	 * 
	 * @Auth 赵光
	 * @Describle 等价于Map《String, Object》, 功能增强
	 */
	public static class ObjectMap extends EasyMap<String, Object> {

		private static final long serialVersionUID = 1L;

		public static ObjectMap newMap() {
			return new ObjectMap();
		}

	}

	/****
	 * 
	 * @Auth 赵光
	 * @Describle 等价于Map《String, Object》, 功能增强
	 */
	public static class StringMap extends EasyMap<String, String> {

		private static final long serialVersionUID = 1L;

		public static StringMap newMap() {
			return new StringMap();
		}
	}
}
